package com.uzai.console.service.impl;

import cn.hutool.core.util.IdUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.uzai.common.enums.WorkOrderBugType;
import com.uzai.common.enums.WorkOrderOptStatus;
import com.uzai.common.enums.WorkOrderOptType;
import com.uzai.common.enums.WorkOrderType;
import com.uzai.common.exception.BusinessException;
import com.uzai.console.common.utils.DingExclusiveGroupUtils;
import com.uzai.console.dto.Materials;
import com.uzai.console.dto.WorkOrderQueryDTO;
import com.uzai.console.dto.dingding.DingExclusiveGroupMessageDto;
import com.uzai.console.dto.workorder.WorkOrderOptDTO;
import com.uzai.console.dto.workorder.WorkOrderReplyDTO;
import com.uzai.console.entity.MerBaseConfig;
import com.uzai.console.entity.WorkOrder;
import com.uzai.console.entity.WorkOrderTalk;
import com.uzai.console.mapper.MerBaseConfigMapper;
import com.uzai.console.mapper.WorkOrderMapper;
import com.uzai.console.mapper.WorkOrderTalkMapper;
import com.uzai.console.service.WorkOrderService;
import com.uzai.console.vo.workorder.WorkOrderReplyVO;
import com.uzai.console.vo.workorder.WorkOrderVO;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

import static com.uzai.common.enums.WorkOrderOptType.*;

/**
 * 工单(WorkOrder)表服务实现类
 *
 * @author mingyang.chen
 * @since 2023-06-16 14:42:58
 */
@Service("workOrderService")
public class WorkOrderServiceImpl extends ServiceImpl<WorkOrderMapper, WorkOrder> implements WorkOrderService {

    @Autowired
    private WorkOrderTalkMapper workOrderTalkMapper;

    @Autowired
    private MerBaseConfigMapper merBaseConfigMapper;

    @Autowired
    private DingExclusiveGroupUtils dingExclusiveGroupUtils;

    List<Integer> continueTalk = Lists.newArrayList(CONTINUE_TALK.getCode(), QA_CONTINUE_TALK.getCode(), PR_CONTINUE_TALK.getCode());

    @Override
    public Object page(WorkOrderQueryDTO param) {

        Page<WorkOrder> page = new Page<>(param.getCurrent(), param.getSize());

        LambdaQueryWrapper<WorkOrder> condition = Wrappers.lambdaQuery(WorkOrder.class);
        condition.eq(WorkOrder::getMerId, param.getMerId());
        if (Objects.nonNull(param.getId())) {
            condition.eq(WorkOrder::getId, param.getId());
        }
        if (Objects.nonNull(param.getType())) {
            condition.eq(WorkOrder::getType, param.getType());
        }
        if (Objects.nonNull(param.getOptStatus())) {
            condition.eq(WorkOrder::getOptStatus, param.getOptStatus());
        }

        condition.orderByDesc(WorkOrder::getUpdateTime);

        Page<WorkOrder> pageObj = this.page(page, condition);

        List<WorkOrderVO> records = pageObj.getRecords().stream().map(item -> {
            WorkOrderVO workOrderVO = new WorkOrderVO();
            BeanUtils.copyProperties(item, workOrderVO);
            List<Materials> materials = JSON.parseArray(item.getImgVideoLink(), Materials.class);
            workOrderVO.setImgVideoLink(materials);
            workOrderVO.setOrderNumber(JSON.parseArray(item.getOrderNumber(), String.class));
            workOrderVO.setUserNumber(JSON.parseArray(item.getUserNumber(), String.class));
            workOrderVO.setOptType(item.getOptWay());
            if (Objects.nonNull(item.getOptWay())) {
                if (continueTalk.contains(item.getOptWay())) {
                    workOrderVO.setOptTypeDesc("继续沟通");
                } else {
                    workOrderVO.setOptTypeDesc(WorkOrderOptType.getByCode(item.getOptWay()).getDesc());
                }
            }
            workOrderVO.setReplyList(getReplyList(item));
            return workOrderVO;
        }).collect(Collectors.toList());

        return new Page<WorkOrderVO>(param.getCurrent(), param.getSize(), pageObj.getTotal()).setRecords(records);
    }

    private List<WorkOrderReplyVO> getReplyList(WorkOrder workOrder) {
        LambdaQueryWrapper<WorkOrderTalk> condition = Wrappers.lambdaQuery(WorkOrderTalk.class);
        condition.eq(WorkOrderTalk::getWorkOrderId, workOrder.getId());

        List<WorkOrderTalk> workOrderTalks = workOrderTalkMapper.selectList(condition);
        if (ObjectUtils.isEmpty(workOrderTalks)) {
            if (StringUtils.isNotBlank(workOrder.getOptResult())) {
                WorkOrderReplyVO workOrderReplyVO = new WorkOrderReplyVO();
                workOrderReplyVO.setId(IdUtil.getSnowflakeNextId());
                workOrderReplyVO.setType(2);
                workOrderReplyVO.setCreateTime(workOrder.getUpdateTime());
                workOrderReplyVO.setReply(workOrder.getOptResult());
                return Lists.newArrayList(workOrderReplyVO);
            }
            return Lists.newArrayList();
        }
        List<WorkOrderReplyVO> replyList = new ArrayList<>();
        for (WorkOrderTalk workOrderTalk : workOrderTalks) {
            WorkOrderReplyVO workOrderReplyVO = new WorkOrderReplyVO();
            BeanUtils.copyProperties(workOrderTalk, workOrderReplyVO);
            if (StringUtils.isNotBlank(workOrderTalk.getImgVideoLink())) {
                workOrderReplyVO.setImgVideoLink(JSON.parseArray(workOrderTalk.getImgVideoLink(), Materials.class));
            }
            replyList.add(workOrderReplyVO);
        }
        return replyList;
    }

    @Override
    public Object add(WorkOrderOptDTO opt) {

        Integer type = opt.getType();
        Integer bugType = opt.getBugType();

        // bug
        if (WorkOrderType.BUG.getCode() == type) {
            if (Objects.isNull(bugType)) {
                throw new BusinessException("bug类型参数错误");
            }
            if (WorkOrderBugType.ORDER.getCode() == bugType && (ObjectUtils.isEmpty(opt.getOrderNumber()) || Objects.isNull(opt.getOrderPlatform()))) {
                throw new BusinessException("平台和订单编号参数错误");
            }

            if (WorkOrderBugType.USER.getCode() == bugType && ObjectUtils.isEmpty(opt.getUserNumber())) {
                throw new BusinessException("用户编号参数错误");
            }
        }

        WorkOrder workOrder = new WorkOrder();
        BeanUtils.copyProperties(opt, workOrder);
        workOrder.setImgVideoLink(JSON.toJSONString(opt.getImgVideoLink()));
        workOrder.setOrderNumber(JSON.toJSONString(opt.getOrderNumber()));
        workOrder.setUserNumber(JSON.toJSONString(opt.getUserNumber()));
        workOrder.setOptStatus(1);
        workOrder.setAcceptTalk(opt.getAcceptTalk());
        workOrder.setCreateTime((int) (System.currentTimeMillis() / 1000L));
        workOrder.setUpdateTime((int) (System.currentTimeMillis() / 1000L));

        this.baseMapper.insert(workOrder);
        if (workOrder.getType() != WorkOrderType.COMPLAINT.getCode()) {
            noticeDingTalk(workOrder);
        }
        return true;
    }

    public void noticeDingTalk(WorkOrder opt) {
        MerBaseConfig config = merBaseConfigMapper.selectByMerId(opt.getMerId(), "dingding_exclusive_group_qrcode_config");
        if (Objects.isNull(config)) {
            log.warn("钉钉群配置未找到");
            return;
        }
        JSONObject configJson = JSON.parseObject(config.getVal());
        if (Objects.isNull(configJson)) {
            log.warn("钉钉群配置解析为空");
            return;
        }
        String openConversationId = configJson.getString("openConversationId");
        if (StringUtils.isBlank(openConversationId)) {
            log.warn("钉钉群配置群id为空");
            return;
        }

        String accessToken = dingExclusiveGroupUtils.getAccessToken(null, null);
        if (StringUtils.isBlank(accessToken)) {
            log.warn("钉钉群AccessToken获取失败, 结果为空");
            return;
        }

        DingExclusiveGroupMessageDto dingExclusiveGroupMessageDto = new DingExclusiveGroupMessageDto();
        dingExclusiveGroupMessageDto.setAccessToken(accessToken);
        dingExclusiveGroupMessageDto.setTargetOpenConversationId(openConversationId);
        dingExclusiveGroupMessageDto.setTitle("工单变更通知");
        dingExclusiveGroupMessageDto.setMessageType("MARKDOWN");

        String content = "需求建议与BUG提交:" + "  \r\n" +
                "工单ID:&nbsp;" + opt.getId() + "  \r\n" +
                "工单类型:&nbsp;" + WorkOrderType.getByCode(opt.getType()).getDesc() + "  \r\n" +
                "需求描述:&nbsp;" + opt.getDesc() + "  \r\n" +
                "处理进度:&nbsp;处理中";
        dingExclusiveGroupMessageDto.setContent(content);

        dingExclusiveGroupUtils.sendingExclusiveGroupMessages(dingExclusiveGroupMessageDto);
    }

    @Override
    public Object reply(WorkOrderReplyDTO opt) {

        Long id = opt.getId();

        WorkOrder workOrder = getById(id);
        if (Objects.isNull(workOrder)) {
            throw new BusinessException("工单不存在");
        }
        Integer optStatus = workOrder.getOptStatus();
        if (WorkOrderOptStatus.WAIT_REPLY.getCode() != optStatus) {
            throw new BusinessException("工单当前状态不支持回复");
        }

        WorkOrderTalk workOrderTalk = new WorkOrderTalk();
        workOrderTalk.setId(IdUtil.getSnowflakeNextId());
        workOrderTalk.setWorkOrderId(workOrder.getId());
        workOrderTalk.setReply(opt.getReply());
        workOrderTalk.setType(1);
        workOrderTalk.setCreateTime((int) (System.currentTimeMillis() / 1000L));
        workOrderTalkMapper.insert(workOrderTalk);

        WorkOrder updateWork = new WorkOrder();
        updateWork.setId(workOrder.getId());
        updateWork.setOptStatus(WorkOrderOptStatus.PROCESSING.getCode());
        updateWork.setUpdateTime((int) (System.currentTimeMillis() / 1000L));

        this.updateById(updateWork);

        return true;
    }

    @Override
    public Object delete(Long id) {

        if (this.removeById(id)) {
            workOrderTalkMapper.deleteByWorkOrderId(id);
        }
        return true;
    }
}

